﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MockUtil;

namespace LHC_Data
{
	public class DataUtil
	{

		#region Métodos Negociais - Interface Pública da Classe.

		public List<DateTime> RetornarUltimos5DiasUteis( DateTime dataInicial )
		{
			int quantidadeDiasUteis = 5;
			return retornarUltimosDias( dataInicial, quantidadeDiasUteis, true );
		}

		public List<DateTime> RetornarUltimos7DiasUteis( DateTime dataInicial )
		{
			if( ! verificarDataValida( dataInicial ) )
			{
				throw new Exception( "A data informada não é válida, por isso não foi possível retornar os últimos 7 dias úteis." );								
			}
			int quantidadeDiasUteis = 7;
			return retornarUltimosDias( dataInicial, quantidadeDiasUteis, true );
		}

		public DateTime RetornarUltimoDiaUtil( DateTime data )
		{
			if( !verificarDataValida( data ) )
			{
				throw new Exception( "Data inválida." );
			}

			DateTime dataModificada = data;
			do
			{
				dataModificada = RetornarUltimoDia( dataModificada );

			} while( !VerificaSeEDiaUtil( dataModificada ) );

			return dataModificada;
		}

		public List<DateTime> RetornarUltimos5DiasCorridos( DateTime dataInicial )
		{
			if( !verificarDataValida( dataInicial ) )
			{
				throw new Exception( "Não foi possivel os últimos 5 dias corridos, favor informar uma data válida" );
			}

			int quantidadeDias = 5;
			return retornarUltimosDias( dataInicial, quantidadeDias, false );
		}

		public List<DateTime> RetornarUltimos7DiasCorridos( DateTime dataInicial )
		{
			if( !verificarDataValida( dataInicial ) )
			{
				throw new Exception( "Favor informar uma data válida" );
			}

			int quantidadeDias = 7;
			return retornarUltimosDias( dataInicial, quantidadeDias, false );
		}

		public List<DateTime> RetornarUltimos30DiasCorridos( DateTime dataInicial )
		{
			if( !verificarDataValida( dataInicial ) )
			{
				throw new Exception( "Impossível recuperar os últimos 30 dias a partir de uma data inválida." );
			}

			int quantidadeDias = 30;
			return retornarUltimosDias( dataInicial, quantidadeDias, false );
		}

		public bool VerificaSeEDiaUtil( DateTime data )
		{
			if( verificaSeEFinalDeSemana( data ) )
			{
				return false;
			}

			return !VerificaSeEFeriado( data );
		}

		public DateTime RetornarUltimoDia( DateTime data )
		{
			return data.AddDays( -1 );
		}

		public bool VerificaSeEFeriado( DateTime data )
		{
			List<DateTime> listaFeriados = MockData.RetornarFeriados();
			
			return ( from d in listaFeriados
						where d.Equals( data )
						select d ).ToList<DateTime>().Count > 0;
		}

		#endregion

		#region Métodos Auxiliares
		private List<DateTime> retornarUltimosDias( DateTime dataInicial, int quantidadeDias, bool diaUtil )
		{
			FiltroData filtro = getFiltroData( dataInicial, quantidadeDias, diaUtil );

			if( diaUtil )
			{
				filtro.DataResult = RetornarUltimoDiaUtil( dataInicial );
			}
			else
			{
				filtro.DataResult = RetornarUltimoDia( dataInicial );
			}

			filtro.ListaUltimosDias = new List<DateTime>();
			filtro.ListaUltimosDias.Add( filtro.DataResult );
			return retornarUltimosDias( filtro );
		}

		private FiltroData getFiltroData( DateTime dataInicial, int quantidadeDias, bool diaUtil )
		{
			FiltroData filtro = new FiltroData();
			filtro.DataInicial = dataInicial;
			filtro.QuantidadeDiasUteis = quantidadeDias;
			filtro.DiaUtil = diaUtil;
			return filtro;
		}

		private List<DateTime> retornarUltimosDias( FiltroData filtro )
		{
			for( int i = 0; filtro.ListaUltimosDias.Count < filtro.QuantidadeDiasUteis; i++ )
			{
				if( filtro.DiaUtil )
				{
					filtro.DataResult = RetornarUltimoDiaUtil( filtro.DataResult );
				}
				else
				{
					filtro.DataResult = RetornarUltimoDia( filtro.DataResult );
				}

				filtro.ListaUltimosDias.Add( filtro.DataResult );
			}
			return filtro.ListaUltimosDias;
		}

		private bool verificaSeEFinalDeSemana( DateTime data )
		{
			return ( data.DayOfWeek == DayOfWeek.Saturday || data.DayOfWeek == DayOfWeek.Sunday );
		}

		private bool verificarDataValida( DateTime dataInicial )
		{
			return dataInicial.Year == 2012;
		}
		
		#endregion
	}
}
